<script lang="ts" setup name="SmartMediaEditor">
import { ElMessage, ElMessageBox } from 'element-plus'
import { Media } from '@/types/smart-media'
import {
  getMediaInfo,
  listAllPublicMediaTags,
  listPublicMediaBasicInfos
} from '@/api/creative/smart-media/media-manager'
import {
  getEditingProjectMaterials,
  addEditingProjectMaterials,
  deleteEditingProjectMaterials,
  getEditingProject,
  updateEditingProject,
  submitMediaProducingJob
} from '@/api/creative/smart-media/production'
import { createAsrJob, getSmartHandleJob } from '@/api/creative/smart-media/media-job'
import './aliyun-video-editor-sdk/index'
import './aliyun-video-editor-sdk/index.css'
import SearchMedia from './components/search-media.vue'
import { transMediaList } from './common/utils'
import ProduceVideo from '@/views/creative/smart-media/components/produce-video.vue'

declare const AliyunVideoEditor: any

const router = useRouter()

let projectId = router.currentRoute.value.query.projectId as string // 项目 ID，由调用方自己保存
const myLocale = 'zh-CN' // 调用方期望的语言

const searchMediaRef = ref<InstanceType<typeof SearchMedia>>()
const produceVideoRef = ref<InstanceType<typeof ProduceVideo>>()

onMounted(() => {
  const config = {
    container: document.querySelector('#aliyun-video-editor'),
    locale: myLocale,
    useDynamicSrc: true,
    getDynamicSrc: async (mediaId: Media['mediaId'], mediaType: Media['mediaType']) => {
      const res = await getMediaInfo({ mediaId: mediaId })

      console.log('通过id获取资源', mediaId, mediaType, res)

      const fileUrl = res.mediaInfo.fileInfoList[0].fileBasicInfo.fileUrl

      return fileUrl.replaceAll('https://md-test-001.oss-cn-hangzhou.aliyuncs.com', '/oss')
    },
    getEditingProjectMaterials: async () => {
      if (projectId) {
        const res = await getEditingProjectMaterials(projectId)
        console.log('获取项目素材: ', res)
        const data = res.mediaInfos
        const transed = transMediaList(data)
        return transed
      }
      return []
    },
    searchMedia: async (mediaType: Media['mediaType']) => {
      // 需要弹窗，下面是弹窗提交后的回调
      const onSubmit = async (materials) => {
        // 组装数据
        const valueObj = {}

        materials.forEach(({ mediaId, mediaBasicInfo: { mediaType } }) => {
          if (!valueObj[mediaType]) {
            valueObj[mediaType] = [mediaId]
          } else {
            valueObj[mediaType].push(mediaId)
          }
        })
        Object.keys(valueObj).forEach((key) => {
          valueObj[key] = valueObj[key].join(',')
        })

        const res = await addEditingProjectMaterials({
          projectId,
          materialMaps: JSON.stringify(valueObj)
        })

        if (res.mediaInfos?.length) return transMediaList(res.mediaInfos)
        return []
      }

      const mediaInfos = await searchMediaRef.value?.open({ multiple: true, mediaType })
      await onSubmit(mediaInfos)
    },
    deleteEditingProjectMaterials: (mediaId: Media['mediaId'], mediaType: Media['mediaType']) =>
      deleteEditingProjectMaterials({
        projectId,
        materialIds: [mediaId],
        materialType: mediaType
      }),
    getStickerCategories: async () => {
      const res = await listAllPublicMediaTags({})

      const stickerCategories = res.mediaTagList.map((item) => ({
        id: item.mediaTagId,
        name: myLocale === 'zh-CN' ? item.mediaTagNameChinese : item.mediaTagNameEnglish // myLocale 是您期望的语言
      }))
      return stickerCategories
    },
    getStickers: async (params: { categoryId: string; page: number; size: number }) => {
      const res = await listPublicMediaBasicInfos({
        mediaTagId: params.categoryId,
        pageNo: params.page,
        pageSize: params.size
      })

      const fileList = res.mediaInfos.map((item) => ({
        mediaId: item.mediaId,
        src: item.fileInfoList?.[0].fileBasicInfo.fileUrl || item.mediaBasicInfo?.inputURL
      }))

      return {
        total: res.totalCount,
        stickers: fileList
      }
    },
    getEditingProject: async () => {
      if (projectId) {
        const res = await getEditingProject({
          projectId,
          requestSource: 'WebSDK'
        })

        const timelineString = (res.project.timeline ?? '{}').replaceAll(
          'https://ice-public-media-hz.oss-cn-hangzhou.aliyuncs.com',
          '/smart-media'
        )
        console.log('timelineString', JSON.parse(timelineString))

        return {
          projectId,
          timeline: timelineString ? JSON.parse(timelineString) : undefined,
          modifiedTime: res.project.ModifiedTime,
          title: res.project.Title // 项目标题
        }
      }
      return {}
    },
    updateEditingProject: async (data: any) => {
      console.log('正在保存项目：', data)
      data.timeline = JSON.stringify(data.timeline)
      const res = await updateEditingProject({
        projectId,
        ...data
      })
      console.log('保存项目结果：', res)
      // WebSDK 本身会进行自动保存，isAuto 则是告诉调用方这次保存是否自动保存，调用方可以控制只在手动保存时才展示保存成功的提示
      !data.isAuto && ElMessage.success('保存成功')
    },
    produceEditingProjectVideo: async (data: any) => {
      const { aspectRatio, timeline, recommend, duration } = data
      // ElMessageBox.alert(
      //   `本次合成视频时长 ${duration} 秒，将会消耗 ${duration * 0.5} 元，您当前的余额为 ${30} 元。`,
      //   '提交合成任务',
      //   {
      //     confirmButtonText: '确定',
      //     callback: (action: Action) => {
      //       ElMessage.success('已提交合成任务，您可在“我的成片”中查看')
      //     }
      //   }
      // )

      const onSubmit = async ({ fileName, format, bitrate, description }) => {
        // 假设提交合成任务的界面让你获得了这些数据
        // 先根据 fileName 和 format 拼接出存储的 mediaURL
        const mediaURL = `https://md-test-001.oss-cn-hangzhou.aliyuncs.com/ice-generated/${fileName}.${format}`
        // 根据 WebSDK 传入的预览比例来决定合成的宽高
        const width = aspectRatio === '16:9' ? 640 : 360
        const height = aspectRatio === '16:9' ? 360 : 640
        // 若视频、图片素材传入的长宽、码率等数据，那么该函数返回的数据中的 recommend 就会包含了根据所使用的视频、图片计算得到的推荐的分辨率和码率
        // recommend 数据结构可以查看 IProduceRecommend
        // 你可以在提交界面上展示推荐数据或者直接使用在提交接口的参数里

        const res = await submitMediaProducingJob({
          outputMediaConfig: JSON.stringify({
            MediaUrl: mediaURL,
            Bitrate: recommend.bitrate || bitrate,
            Width: recommend.width || width,
            Height: recommend.height || height
          }),
          outputMediaTarget: 'oss-object',
          projectMetadata: JSON.stringify({ Description: description }),
          projectId,
          timeline: JSON.stringify(timeline)
        })
        console.log('🚀 ~ file: editor.vue:188 ~ onSubmit ~ res:', res)
        if (res?.jobId) {
          ElMessageBox.alert('提交任务成功，请前往“素材管理”页面查看结果。', '提交成功', {
            confirmButtonText: '确定',
            callback: () => {}
          })
        } else {
          ElMessage.error('生成视频失败')
        }
      }

      const formValues = await produceVideoRef.value?.open(data)
      onSubmit(formValues)
    },
    submitASRJob: async (mediaId: any, startTime: string, duration: string) => {
      const createRes = await createAsrJob({
        inputFile: mediaId,
        startTime,
        duration
      })
      const jobId = createRes.jobId
      while (true) {
        const res = await getSmartHandleJob({ jobId })

        switch (res.state) {
          case 'Finished':
            console.log('res.jobResult.aiResult', res)

            return JSON.parse(res.jobResult.aiResult)
          case 'Failed':
            return null
        }
        await new Promise<void>((resolve) => setTimeout(resolve, 1000))
      }
    }
  }

  AliyunVideoEditor.init(config)
})
</script>

<template>
  <div class="absolute top-4 left-4 right-4 bottom-4 bg-blue-300">
    <!-- 剪辑工具挂载div -->
    <div id="aliyun-video-editor" class="w-full h-full"></div>

    <!-- 搜索媒资弹窗 -->
    <SearchMedia ref="searchMediaRef" />

    <!-- 视频合成表单弹窗 -->
    <ProduceVideo ref="produceVideoRef" />
  </div>
</template>

<style scoped></style>
